package com.zkyc.framework.website.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zkyc.framework.common.exception.ResultCode;
import com.zkyc.framework.common.mapper.FileMapper;
import com.zkyc.framework.common.pojo.Association;
import com.zkyc.framework.common.pojo.File;
import com.zkyc.framework.common.pojo.WebRefAssociation;
import com.zkyc.framework.common.vo.ResultVO;
import com.zkyc.framework.website.mapper.AssociationMapper;
import com.zkyc.framework.website.mapper.WebRefAssociationMapper;
import com.zkyc.framework.website.service.AssociationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * (Association)表服务实现类
 *
 * @author wj
 * @since 2022-11-15 19:06:07
 */
@Slf4j
@Service("associationService")
public class AssociationServiceImpl implements AssociationService {
    @Autowired
    private AssociationMapper associationMapper;
    @Autowired
    private WebRefAssociationMapper refAssociationMapper;
    @Autowired
    private FileMapper fileMapper;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Association queryById(Integer id) {
        Association association = associationMapper.selectById(id);
        subHandleAssociationFiles(association);
        return association;
    }

    private void subHandleAssociationFiles(Association association) {
        if (association == null) {
            return;
        }
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = getRefAssociationLqw();
        refAssociationLqw.eq(WebRefAssociation::getAssociationId, association.getId());
        // 根据id升序
        List<WebRefAssociation> webRefAssociationList = refAssociationMapper.selectList(refAssociationLqw);
        if (CollectionUtils.isEmpty(webRefAssociationList)) {
            return;
        }
        Map<Long, File> fileIdFileMap = getFileIdFileMap(webRefAssociationList);
        microHandleAssociationFiles(fileIdFileMap, association, webRefAssociationList);
    }

    /**
     * 分页查询
     *
     * @return 查询结果
     */
    @Override
    public ResultVO queryByPage() {
        List<Association> associations = associationMapper.selectList(null);
        handleAssociationFiles(associations);
        List<Association> associationTree = getAssociationTree(associations);
        return ResultVO.data(associationTree);
    }

    private void handleAssociationFiles(List<Association> associations) {
        if (CollectionUtils.isEmpty(associations)) {
            return;
        }
        List<Integer> associationIdList = associations.stream().map(Association::getId).collect(Collectors.toList());
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = new LambdaQueryWrapper<>();
        refAssociationLqw.select(WebRefAssociation::getAssociationId, WebRefAssociation::getFileId);
        refAssociationLqw.in(WebRefAssociation::getAssociationId, associationIdList);
        // .orderByAsc(WebRefAssociation::getId);
        List<WebRefAssociation> webRefAssociationList = refAssociationMapper.selectList(refAssociationLqw);
        if (CollectionUtils.isEmpty(webRefAssociationList)) {
            return;
        }
        // 中间表分组，需要注意顺序；文件集合转map
        Map<Integer, List<WebRefAssociation>> associationIdRefFileMap =
                webRefAssociationList.stream().collect(Collectors.groupingBy(WebRefAssociation::getAssociationId, LinkedHashMap::new, Collectors.toList()));
        Map<Long, File> fileIdFileMap = getFileIdFileMap(webRefAssociationList);
        // 填充数据
        for (int i = 0; i < associations.size(); i++) {
            Association association = associations.get(i);
            List<WebRefAssociation> webRefAssociationListTemp = associationIdRefFileMap.get(association.getId());
            if (!CollectionUtils.isEmpty(webRefAssociationListTemp)) {
                microHandleAssociationFiles(fileIdFileMap, association, webRefAssociationListTemp);
            }
        }
    }

    private void microHandleAssociationFiles(Map<Long, File> fileIdFileMap, Association association, List<WebRefAssociation> webRefAssociationListTemp) {
        List<File> fileListTemp = webRefAssociationListTemp.stream().map(webRefAssociation -> fileIdFileMap.get(webRefAssociation.getFileId())).collect(Collectors.toList());
        // 分为图片和视频
        Map<String, List<File>> typeFilesMap = fileListTemp.stream().collect(Collectors.groupingBy(File::getType, LinkedHashMap::new, Collectors.toList()));
        association.setSilhouette(typeFilesMap.get("0"));
        association.setVideo(typeFilesMap.get("1"));
    }

    private Map<Long, File> getFileIdFileMap(List<WebRefAssociation> webRefAssociationList) {
        // 正常不会重复，不需要去重
        List<Long> fileIdList = webRefAssociationList.stream().map(WebRefAssociation::getFileId).collect(Collectors.toList());
        LambdaQueryWrapper<File> fileLqw = new LambdaQueryWrapper<>();
        fileLqw.select(File::getId, File::getFileName, File::getType, File::getCoverUrl, File::getUrl, File::getWatermarkUrl, File::getCreateTime);
        fileLqw.in(File::getId, fileIdList);
        List<File> fileList = fileMapper.selectList(fileLqw);
        return fileList.stream().collect(Collectors.toMap(File::getId, file -> file));
    }

    /**
     * 新增数据
     *
     * @param association 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional
    public ResultVO insert(Association association) {
        if (association == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        association.setIsDelete(0);
        associationMapper.insert(association);
        // 插入中间表
        try {
            handleInsertRef(association);
        } catch (Exception e) {
            log.error("新增协会发生异常：" + e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultVO.fail(e.getMessage());
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private void handleInsertRef(Association association) {
        List<WebRefAssociation> webRefAssociationList = new ArrayList<>();
        List<File>[] fileListArray = new List[2];
        fileListArray[0] = association.getSilhouette();
        fileListArray[1] = association.getVideo();

        Date date = new Date();
        for (int i = 0; i < fileListArray.length; i++) {
            if (!CollectionUtils.isEmpty(fileListArray[i])) {
                for (File file : fileListArray[i]) {
                    if (file == null || file.getId() ==null) {
                        throw new RuntimeException("文件上传异常");
                    }
                    WebRefAssociation webRefAssociation = new WebRefAssociation();
                    webRefAssociation.setAssociationId(association.getId());
                    webRefAssociation.setCreateTime(date);
                    webRefAssociation.setFileId(file.getId());
                    webRefAssociation.setFileType(i);
                    webRefAssociationList.add(webRefAssociation);
                }
            }
        }
        // 不为空时才需要插入
        if (CollectionUtils.isEmpty(webRefAssociationList)) {
            return;
        }
        refAssociationMapper.insertBatch(webRefAssociationList);
    }

    /**
     * 修改数据
     *
     * @param association 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional
    public ResultVO update(Association association) {
        if (association == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(association.getId()) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        associationMapper.updateById(association);
        // 中间表先删
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = getRefAssociationLqw();
        refAssociationLqw.eq(WebRefAssociation::getAssociationId, association.getId());
        refAssociationMapper.delete(refAssociationLqw);
        // 后增
        try {
            handleInsertRef(association);
        } catch (Exception e) {
            log.error("编辑协会发生异常：" + e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultVO.fail(e.getMessage());
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private LambdaQueryWrapper<WebRefAssociation> getRefAssociationLqw() {
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = new LambdaQueryWrapper<>();
        refAssociationLqw.select(WebRefAssociation::getAssociationId, WebRefAssociation::getFileId);

        // refAssociationLqw.orderByAsc(WebRefAssociation::getId);
        return refAssociationLqw;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public ResultVO deleteById(Integer id) {
        if (id == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(id) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        associationMapper.deleteById(id);
        // 这里中间表也要删除，不然会产生脏数据
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = getRefAssociationLqw();
        refAssociationLqw.eq(WebRefAssociation::getAssociationId, id);
        refAssociationMapper.delete(refAssociationLqw);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO querySilhouetteByPage(Integer associationId, Integer fileType, Integer current, Integer size) {
        IPage<WebRefAssociation> page = new Page<>(current, size);
        LambdaQueryWrapper<WebRefAssociation> refAssociationLqw = getRefAssociationLqw();
        if (associationId != null) {
            refAssociationLqw.eq(WebRefAssociation::getAssociationId, associationId);
        }
        refAssociationLqw.eq(WebRefAssociation::getFileType, fileType);
        IPage<WebRefAssociation> webRefAssociationIPage = refAssociationMapper.selectPage(page, refAssociationLqw);
        // 转为文件列表
        List<WebRefAssociation> webRefAssociationList = webRefAssociationIPage.getRecords();
        if (CollectionUtils.isEmpty(webRefAssociationList)) {
            // 为空直接返回
            return ResultVO.data(webRefAssociationIPage);
        }
        Map<Long, File> fileIdFileMap = getFileIdFileMap(webRefAssociationList);
        List<File> fileList = webRefAssociationList.stream().map(webRefAssociation -> fileIdFileMap.get(webRefAssociation.getFileId())).collect(Collectors.toList());
        IPage<File> filePage = new Page<>();
        BeanUtils.copyProperties(webRefAssociationIPage, filePage);
        filePage.setRecords(fileList);
        return ResultVO.data(filePage);
    }

    @Override
    public ResultVO querySilhouetteById(Long id) {
        File file = fileMapper.selectById(id);
        return ResultVO.data(file);
    }


    public static List<Association> getAssociationTree(List<Association> AssociationList) {
        return AssociationList.stream()
                // 筛选出父节点
                .filter(t -> t.getParentId() == 0)
                // 设置父节点的子节点列表
                .peek(item -> item.setChildren(streamGetChildren(item, AssociationList)))
                .collect(Collectors.toList());
    }

    /**
     * stream 方式递归查找子节点列表
     *
     * @return 王健
     */
    public static List<Association> streamGetChildren(Association Association, List<Association> AssociationList) {
        return AssociationList.stream()
                .filter(t -> t.getParentId().equals(Association.getId()))
                .peek(item -> item.setChildren(streamGetChildren(item, AssociationList)))
                .collect(Collectors.toList());
    }
}
